package com.etime.shycourse.services.account.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.etime.shycourse.services.account.interfaces.OnlineCourseAccountService;
import com.etime.shycourse.dao.*;
import com.etime.shycourse.orde.dao.OrderdetailMapper;
import com.etime.shycourse.orde.dao.OrdersMapper;
import com.etime.shycourse.orde.pojo.Orderdetail;
import com.etime.shycourse.orde.pojo.Orders;
import com.etime.shycourse.pojo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 在线课程提成结算实现类
 */
@Service
public class OnlineCourseAccountServiceImpl implements OnlineCourseAccountService {

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderdetailMapper orderdetailMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SalerMapper salerMapper;
    @Autowired
    private TakesliceMapper takesliceMapper;
    @Autowired
    private SettlementMapper settlementMapper;
    @Autowired
    private OrgTeacherMapper teacherMapper;
    @Autowired
    private OrganizationMapper organizationMapper;
    /**
     * 在线课程提成结算接口
     * 1、根据订单获取订单明细列表
     * 2、计算每个订单明细的提成计算金额
     *    计算方式：订单明细提成金额 = 订单总支付金额x订单明细价格/（所有订单明细价格之和）
     * -------------
     * 下面计算:分别计算每一个订单明细的提成金额
     * 4、计算销售提成
     * 5、计算教师（机构）提成
     * 6、修改订单明细表-->提成计算结果保存
     * 7、修改订单表-->已结算
     * 8、保存财务结算表
     * -----------
     * 提成比例规则：
     * 1、如果课程中设置了提成比例，则按照课程中设置的比例进行提成；
     * 2、如果没有设置课程提成比例，则按照销售和教师/机构设置的提成比例进行提成计算；
     * 3、如果都没有设置，则按照统一的提成比例进行计算；
     * @param orders 订单实体
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void onlineCourseAccount(Orders orders) {
        //1、根据订单获取订单明细列表
        List<Orderdetail> orderdetailList = selectOrderDetails(orders.getOrderid());
        //2、计算每个订单明细的提成计算金额
        orderdetailList = dealCoursePay(orderdetailList,orders);
        //针对每一个订单明细进行提成计算
        for(Orderdetail detail : orderdetailList){
            //查询订单明细所对应的课程信息
            Course course = courseMapper.selectById(detail.getOdcourseid());
            //计算销售提成
            salerAcount(orders,detail,course);
            if(course.getCoursetecorg()==1){
                //计算教师提成
                techerAccount(orders,detail,course);
            }else{
                //计算机构提成
                orgAccount(orders,detail,course);
            }
            //保存订单明细
            orderdetailMapper.updateById(detail);
        }
        //修改订单结算状态为：已结算
        orders.setOrderaccountstate(1);
        ordersMapper.updateById(orders);
    }

    /**
     * 计算机构提成
     * 0 如果没有设置课程所属机构，或者课程属于独立教师则不计算提成
     *  一、获取机构提成比例
     *  1、首先从课程中获取教师/机构提成比例，如果有则直接使用
     *  2、根据课程所属机构id查询机构信息，从机构信息中获取机构提成比例；
     *  3、获取统一的机构提成比例
     *  二、计算
     *  机构提成金额 = 订单明细计算提成金额*提成比例
     *  三、保存
     *  1、保存记录到detail实体；
     *  2、保存记录到财务结算记录表
     * @param orders
     * @param detail
     * @param course
     */
    private void orgAccount(Orders orders, Orderdetail detail, Course course) {
        if(course.getCourseorgid()!=null && course.getCourseorgid()!=-2){
            BigDecimal point = null;
            if(course.getCoursetecpoint()!=null && course.getCoursetecpoint()>0){
                point = new BigDecimal(course.getCoursetecpoint()).setScale(2,BigDecimal.ROUND_HALF_UP);
            }else{
                //获取机构的提成比例
                Organization org = organizationMapper.selectByIds(course.getCourseorgid());
                if(org!=null){
                   if(org.getOrgtakepoint()!=null && org.getOrgtakepoint().compareTo(new BigDecimal(-1))!=0){
                        point = org.getOrgtakepoint();
                    }else{
                       //使用统一设置的提成比例
                       Takeslice takeslice = takesliceMapper.selectById(0);
                       if(takeslice!=null){
                           point = takeslice.getOrgpoint();
                       }
                   }
                }
            }
            //计算
            if(point!=null){
                BigDecimal orgTakes = point.multiply(detail.getOdpay()).setScale(2,BigDecimal.ROUND_HALF_UP);
                //保存计算结果到订单明细实体
                detail.setOdtectakes(orgTakes);
                detail.setOdtecsettlement(1);
                detail.setOdtectime(new Date());
                //保存财务结算记录
                Settlement settlement = new Settlement();
                settlement.setOdid(detail.getOdid());
                settlement.setSettlementtype(1);
                settlement.setSettlementuserid(course.getCourseorgid());
                settlement.setSettlementsale(detail.getOdpay());
                settlement.setSettlementpoint(point);
                settlement.setSettlementamount(orgTakes);
                settlement.setSettlementtime(new Date());
                settlement.setSettlementpay(0);
                int rtn = settlementMapper.insert(settlement);
                if(rtn>0){
                    System.out.println("结算机构提成成功："+settlement.toString());
                }else{
                    System.out.println("结算机构提成失败："+settlement.toString());
                }
            }
        }else{
            //不计算机构提成(机构教师使用相同字段)
            detail.setOdtectakes(new BigDecimal(0).setScale(2,BigDecimal.ROUND_HALF_UP));
            detail.setOdtecsettlement(1);
            detail.setOdtectime(new Date());
        }
    }

    /**
     * 计算教师提成
     *  0、判断课程是否有教师设置，如果没有，则不进行提成；
     *  一、获取教师的提成比例
     *  1、先从课程中获取课程的教师提成比例，如果有，则直接使用；
     *  2、如果课程中没有教师的提成比例，则根据课程中的教师id查询教师信息，然后从教师信息中获取
     *  提成比例；
     *  3、如果教师的提成比例是-1，则查询统一的提成比例；
     *  二、计算
     *  1、教师提成金额=订单明细中的提成计算金额*提成比例
     *  三、保存
     *  1、保存计算结果到orderdetail实体中；
     *  2、保存财务结算记录到数据库
     * @param orders
     * @param detail
     * @param course
     */
    private void techerAccount(Orders orders, Orderdetail detail, Course course) {
        if(course.getCourseteacherid()!=null && course.getCourseteacherid()!=-1){
            //获取教师提成比例
            BigDecimal point = null;
            //查询教师信息
            Teacher teacher = teacherMapper.selectById(course.getCourseteacherid());
            //教师的用户id
            Integer tecuserid = teacher.getUserid();
            if(course.getCoursetecpoint()!=null && course.getCoursetecpoint()>0){
                point = new BigDecimal(course.getCoursetecpoint()).setScale(2,BigDecimal.ROUND_HALF_UP);
            }else{
                //获取教师的提成比例
                if(teacher.getTectakepoint()==null || teacher.getTectakepoint().compareTo(new BigDecimal(-1))==0){
                    //使用统一提成比例
                    Takeslice takeslice = takesliceMapper.selectById(0);
                    if(takeslice!=null){
                        point = takeslice.getTecpoint();
                    }
                }else{
                    point = teacher.getTectakepoint();
                }

            }
            //计算
            if(point!=null){
                BigDecimal tecTakes = point.multiply(detail.getOdpay()).setScale(2,BigDecimal.ROUND_HALF_UP);
                //保存计算结果到订单明细实体
                detail.setOdtectakes(tecTakes);
                detail.setOdtecsettlement(1);
                detail.setOdtectime(new Date());
                //保存财务结算记录
                Settlement settlement = new Settlement();
                settlement.setOdid(detail.getOdid());
                settlement.setSettlementtype(3);
                settlement.setSettlementuserid(tecuserid);
                settlement.setSettlementsale(detail.getOdpay());
                settlement.setSettlementpoint(point);
                settlement.setSettlementamount(tecTakes);
                settlement.setSettlementtime(new Date());
                settlement.setSettlementpay(0);
                int rtn = settlementMapper.insert(settlement);
                if(rtn>0){
                    System.out.println("结算教师提成成功："+settlement.toString());
                }else{
                    System.out.println("结算教师提成失败："+settlement.toString());
                }
            }
        }else{
            //不计算教师提成
            detail.setOdtectakes(new BigDecimal(0).setScale(2,BigDecimal.ROUND_HALF_UP));
            detail.setOdtecsettlement(1);
            detail.setOdtectime(new Date());
        }
    }

    /**
     * 计算销售提成
     * 1、根据订单的用户查询该用户所对应的销售人员id
     * 2、如果没有销售人员id，则该笔订单不计算销售人员提成；
     * 3、计算销售人员提成比例-->课程的销售提成比例>销售人员个人的提成比例>统一的提成比例
     * 4、提成金额=订单明细的提成金额*提成比例
     * 5、保存财务结算记录；保存订单明细记录（修改订单明细实体中的属性）
     * @param orders 订单信息
     * @param detail 订单明细信息
     * @param course 课程信息
     */
    private void salerAcount(Orders orders, Orderdetail detail, Course course) {
        //1、查询用户信息（根据id查询）
        SysUser sysUser = sysUserMapper.selectById(orders.getOrderuserid());
        //2、如果没有销售人员id，则该笔订单不计算销售人员提成；
        if(sysUser.getSaleruserid()!=null && sysUser.getSaleruserid()!=-1){
            //计算提成
            BigDecimal point = null;
            //课程中是否设置了提成比例
            if(course.getCoursesalerpoint()!=null && course.getCoursesalerpoint()>0){
                point = new BigDecimal(course.getCoursesalerpoint()).setScale(2,BigDecimal.ROUND_HALF_UP);
            }else{
                //获取销售人员的提成比例(查询销售人员)
                Saler saler = selectSalerByUserid(sysUser.getSaleruserid());
                if(saler!=null){
                    if(saler.getSalertakepoint().compareTo(new BigDecimal(-1))==0){
                        //使用统一的提成比例
                        Takeslice takeslice = takesliceMapper.selectById(0);
                        if(takeslice!=null){
                            point = takeslice.getSalerpoint();
                        }

                    }else{
                        //个人提成比例
                        point = saler.getSalertakepoint();
                    }
                }
            }
            //计算提成，如果没有设置提成比例，则不进行提成计算
            if(point!=null){
                //计算：提成=明细提成金额*提成比例。四舍五入保留两位小数
                BigDecimal salerTakes = detail.getOdpay().multiply(point).setScale(2,BigDecimal.ROUND_HALF_UP);
                //保存计算结果到订单实体中
                detail.setOdsalertakes(salerTakes);
                detail.setOdsalersettlemented(1);
                detail.setOdsalertime(new Date());
                //保存财务结算记录
                Settlement settlement = new Settlement();
                settlement.setOdid(detail.getOdid());
                settlement.setSettlementtype(2);
                settlement.setSettlementuserid(sysUser.getSaleruserid());
                settlement.setSettlementsale(detail.getOdpay());
                settlement.setSettlementpoint(point);
                settlement.setSettlementamount(salerTakes);
                settlement.setSettlementtime(new Date());
                settlement.setSettlementpay(0);
                int rtn = settlementMapper.insert(settlement);
                if(rtn>0){
                    System.out.println("结算销售提成成功："+settlement.toString());
                }else{
                    System.out.println("结算销售提成失败："+settlement.toString());
                }
            }
        }else{
            //不计算销售提成
            detail.setOdsalertakes(new BigDecimal(0.00));
            detail.setOdsalersettlemented(1);
            detail.setOdsalertime(new Date());
        }
    }

    /**
     * 根据用户id查询销售人员信息
     * @param saleruserid 销售人员用户id
     * @return
     */
    private Saler selectSalerByUserid(Integer saleruserid) {
        QueryWrapper<Saler> wrapper = new QueryWrapper<>();
        wrapper.eq("userid",saleruserid);
        List<Saler> list = salerMapper.selectList(wrapper);
        if(list!=null && list.size()>0){
            return list.get(0);
        }else{
            return null;
        }
    }

    /**
     * 处理计算订单中每个课程的实际支付金额，用于计算提成
     * @param orderdetailList 订单明细
     * @param orders 订单
     * @return
     */
    private List<Orderdetail> dealCoursePay(List<Orderdetail> orderdetailList,Orders orders){
        if(orderdetailList!=null && orderdetailList.size()>0){
            if(orderdetailList.size()==1){
                //如果订单只有一个课程，那么课程的提成计算金额=订单总支付金额
                orderdetailList.get(0).setOdpay(orders.getOrderpaycash());
            }else{
                //订单总共应该支付金额
                BigDecimal orderpayamount = orders.getOrderpayamount();
                //订单实际支付金额
                BigDecimal orderpaycash = orders.getOrderpaycash();
                for (int i = 0; i < orderdetailList.size(); i++) {
                    //订单明细价格
                    BigDecimal odprice = orderdetailList.get(i).getOdprice();
                    //如果有多个课程，那么按照提成金额=支付金额*（课程价格/总应付金额）;
                    //所有计算保留两位小数(四舍五入)
                    orderdetailList.get(i).setOdpay(
                            odprice.divide(orderpayamount,
                                    2,
                                    BigDecimal.ROUND_HALF_UP)
                                    .multiply(orderpaycash)
                                    .setScale(2,BigDecimal.ROUND_HALF_UP));
                }
            }
        }
        return orderdetailList;
    }

    /**
     * 根据订单id查询订单详细信息
     * @param orderid
     * @return
     */
    private List<Orderdetail> selectOrderDetails(Integer orderid){
        QueryWrapper<Orderdetail> wrapper = new QueryWrapper<>();
        wrapper.eq("orderid",orderid);
        return orderdetailMapper.selectList(wrapper);
    }
}
